using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
using System.Web.Services.Protocols;
using Microsoft.Office.Project.Server.Library;
using Microsoft.Office.Project.Server.Events;
using Microsoft.SharePoint;
using MSPE.Public.FOSS.AutoStatusPlus.Common;

namespace MSPE.Public.FOSS.AutoStatusPlus.EventHandler
{
    public class TSEventHandler : TimesheetEventReceiver
    {
        #region Private / Protected
        private EventEntry _eventLog;
        private Settings _loadedSettings;
        private const string _eventSourceName = "AutoStatusPlus TSEventHandler";
        #endregion // Private / Protected

        #region Constructors
        /// <summary>
        /// Constructs a new instance of the <see cref="TSEventHandler" /> class.
        /// </summary>
        public TSEventHandler()
        {
            _eventLog = new EventEntry(_eventSourceName);
        } // TSEventHandler()
        #endregion // Constructors

        #region Methods
        #region Overrides
        public override void OnUpdated(PSContextInfo contextInfo, TimesheetPostEventArgs e)
        {
            _loadedSettings = Utility.LoadSettings(contextInfo.SiteGuid);
            
            if (_loadedSettings.Event == (TimesheetEventEnum)Enum.Parse(typeof(TimesheetEventEnum), MethodBase.GetCurrentMethod().Name))
                QueueApproval(contextInfo.SiteGuid, e.TsUID, contextInfo.Lcid, contextInfo.UserName);
        }

        public override void OnUpdating(PSContextInfo contextInfo, TimesheetPreUpdateEventArgs e)
        {
            _loadedSettings = Utility.LoadSettings(contextInfo.SiteGuid);

            if (_loadedSettings.Event == (TimesheetEventEnum)Enum.Parse(typeof(TimesheetEventEnum), MethodBase.GetCurrentMethod().Name))
                QueueApproval(contextInfo.SiteGuid, e.TsUID, contextInfo.Lcid, contextInfo.UserName);
        }

        public override void OnSubmitted(PSContextInfo contextInfo, TimesheetPostEventArgs e)
        {
            _loadedSettings = Utility.LoadSettings(contextInfo.SiteGuid);

            if (_loadedSettings.Event == (TimesheetEventEnum)Enum.Parse(typeof(TimesheetEventEnum), MethodBase.GetCurrentMethod().Name))
                QueueApproval(contextInfo.SiteGuid, e.TsUID, contextInfo.Lcid, contextInfo.UserName);
        }

        public override void OnSubmitting(PSContextInfo contextInfo, TimesheetPreSubmitEventArgs e)
        {
            _loadedSettings = Utility.LoadSettings(contextInfo.SiteGuid);

            if (_loadedSettings.Event == (TimesheetEventEnum)Enum.Parse(typeof(TimesheetEventEnum), MethodBase.GetCurrentMethod().Name))
                QueueApproval(contextInfo.SiteGuid, e.TsUID, contextInfo.Lcid, contextInfo.UserName);
        }

        public override void OnReviewed(PSContextInfo contextInfo, TimesheetPostEventArgs e)
        {
            WebServiceManager _webRefMgr = new WebServiceManager();
            _loadedSettings = Utility.LoadSettings(contextInfo.SiteGuid);

            if (_loadedSettings.Event == (TimesheetEventEnum)Enum.Parse(typeof(TimesheetEventEnum), MethodBase.GetCurrentMethod().Name))
            {
                SPSite _pwaSite = null;
                TimesheetSvc.TimesheetDataSet _timesheetData = null;

                try
                {
                    _pwaSite = new SPSite(contextInfo.SiteGuid);

                    _webRefMgr.PwaUrl = _pwaSite.Url;
                    TimesheetSvc.TimeSheet _timesheet = _webRefMgr.GetWebRef(WebServiceTypeEnum.TimeSheet) as TimesheetSvc.TimeSheet;

                    if (_timesheet == null)
                        throw new Exception("Unable to initialize Web Service Reference!");

                    // Retrieve the timesheet that raised the event
                    _timesheetData = _timesheet.ReadTimesheet(e.TsUID);

                    // todo: fix so that it doesn't show the approver
                    // Only act on approved timesheets
                    if (_timesheetData.Headers[0].TS_STATUS_ENUM == (byte)TimesheetEnum.Status.Approved)
                        QueueApproval(contextInfo.SiteGuid, e.TsUID, contextInfo.Lcid, contextInfo.UserName);
                } // End try

                catch (SoapException ex)
                {
                    throw Utility.ExpandPsiException(ex);
                } // End catch

                finally
                {
                    if (_pwaSite != null) _pwaSite.Dispose();
                    if (_timesheetData != null) _timesheetData.Dispose();
                } // End finally
            }
        }

        public override void OnReviewing(PSContextInfo contextInfo, TimesheetPreReviewEventArgs e)
        {
            _loadedSettings = Utility.LoadSettings(contextInfo.SiteGuid);

            if (_loadedSettings.Event == (TimesheetEventEnum)Enum.Parse(typeof(TimesheetEventEnum), MethodBase.GetCurrentMethod().Name))
            {
                // Make sure the timesheet was approved
                if ((TimesheetEnum.Action)Enum.Parse(typeof(TimesheetEnum.Action), e.Action.ToString()) == TimesheetEnum.Action.Approve)
                    // todo: fix so that it doesn't show the approver
                    QueueApproval(contextInfo.SiteGuid, e.TsUID, contextInfo.Lcid, contextInfo.UserName);
            }
        }
        #endregion // Overrides
        
        private void QueueApproval(Guid siteGuid, Guid tsGuid, string lcid, string userName)
        {
            SqlCommand _cmdAdd = null;
            SqlConnection _cn = null;
            string _connString = Utility.BuildConnectionString(_loadedSettings.DbUseIntegratedAuth,
                                                               _loadedSettings.DbServer, _loadedSettings.DbName,
                                                               _loadedSettings.DbUser, _loadedSettings.DbPassword);
            try
            {
                if (_connString == null)
                {
                    _eventLog.WriteEvent("Connection string is null.");
                    return;
                }
                using (_cn = new SqlConnection(_connString))
                {
                    _cn.Open();
                    _cmdAdd = new SqlCommand(GlobalConstants.SqlAddTimesheetProcName, _cn);
                    _cmdAdd.CommandType = CommandType.StoredProcedure;
                    SqlParameter _parm = new SqlParameter("@siteGuid", SqlDbType.UniqueIdentifier);
                    _parm.Value = siteGuid;
                    _cmdAdd.Parameters.Add(_parm);
                    _parm = new SqlParameter("@tsGuid", SqlDbType.UniqueIdentifier);
                    _parm.Value = tsGuid;
                    _cmdAdd.Parameters.Add(_parm);
                    _parm = new SqlParameter("@lcid", SqlDbType.NVarChar, 50);
                    _parm.Value = lcid;
                    _cmdAdd.Parameters.Add(_parm);
                    _parm = new SqlParameter("@userName", SqlDbType.NVarChar, 50);
                    _parm.Value = userName;
                    _cmdAdd.Parameters.Add(_parm);
                    _cmdAdd.ExecuteNonQuery();
                }
            }
            catch (Exception ex)
            {
                _eventLog.WriteEvent(ex.Message + "\nError in " + MethodBase.GetCurrentMethod().Name);
            }

            finally
            {
                if (_cn != null)
                {
                    if (_cn.State != ConnectionState.Closed)
                    {
                        _cn.Close();
                    }
                }

                if (_cmdAdd != null) _cmdAdd.Dispose();
            }
        }
        #endregion // Methods
    }
}
